from OpenGL.raw.GL.constants import GL_DEPTH_TEST
from OpenGL.raw.GL import glLoadMatrixf
import pygame
from pygame.locals import *
from game.client.gui.widget import *

class Label(Widget):
    def __init__(self, text="", **args):
        Widget.__init__(self, **args)
        self.text = text
        self.build_text()

    #Will make the dimensions of the label just fit the size of the text.
    #The origin of this widget's rect will remain the same
#    def pack(self):
#        self.pos.size = self.constrain(self.font.size(self.text))
#        return self.pos.size

    def set_text(self, text):
        self.text = text
        self.redraw()
        
    def redraw(self):
        self.build_text()
        if self.parent is not None:
            self.parent.redraw()


    def build_text(self):
        #Generate PyOpenGL Texture
        self.texture = glGenTextures(1)
        self.surface = pygame.Surface(self.pos.size(), SRCALPHA)
        self.surface.fill((0,0,0,0))
        #Convert it to load any alpha channel
        self.surface.convert_alpha()

        offset = [0, 0]
        w, h = self.font.size(self.text)
        #take into account the aligns
        #center horizontal align
        if self.align == 0:
            offset[0] = (self.pos.width() - w) // 2

        #right align
        elif self.align == 1:
            offset[0] = self.pos.width() - w

        if self.valign == 0:
            offset[1] = (self.pos.height() - h) // 2
        elif self.valign == 1:
            offset[1] = self.pos.height() - h

        #Surface.blit(self.font.render(self.text, True, self.color), (offset[0], offset[1]))
        self.surface.blit(self.font.render(self.text, True, self.color), (offset[0], offset[1]))

        #Convert to PyOpenGL Data
        Data = pygame.image.tostring(self.surface, "RGBA", 1)
        #Select our Texture Object
        glBindTexture(GL_TEXTURE_2D, self.texture)
        #Load the Data into the Texture
        glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, self.surface.get_width(),
            self.surface.get_height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, Data )
        #Define some Parameters for this Texture
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)


class FpsLabel(Label):
    def __init__(self, clock, **args):
        Label.__init__(self, "", **args)
        self.clock = clock

    def draw(self):
        print 'called'
        self.set_text("{:.2f} FPS".format(self.clock.get_fps()))
        Label.draw(self)

class Billboard(Label):
    def __init__(self, text, pos, **args):
        Label.__init__(self, text, **args)
        self.pos = pos

    def draw(self):
        if self.display_list is None:
            self.build_display()

        glDisable(GL_TEXTURE_2D)
        glDisable(GL_LIGHTING)
        if self.texture is None:
            glColor4d(*self.color)
        else:
            glEnable(GL_TEXTURE_2D)
            #glEnable(GL_ALPHA_TEST)
            glEnable(GL_BLEND)
            #glAlphaFunc(GL_GREATER, 0.0)
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
            glColor3f(255,255,255)
            glBindTexture(GL_TEXTURE_2D, self.texture)

        glPushMatrix()
        glTranslate(*self.pos)
        mat = glGetDoublev(GL_MODELVIEW_MATRIX)
        for i in xrange(3):
            for j in xrange(3):
                if i == j:
                    mat[i][j] = 1
                else:
                    mat[i][j] = 0
        glLoadMatrixf(mat)
        #glLoadIdentity()
        #print mat
        glDisable(GL_DEPTH_TEST)
        glCallList(self.display_list)
        glEnable(GL_DEPTH_TEST)
        glPopMatrix()

        if self.texture is not None:
            glDisable(GL_TEXTURE_2D)

    def build_display(self):
        t, l, b, r, z = self.rect.top, self.rect.left, self.rect.bottom, self.rect.right, self.zindex
        if self.texture is None:
            self.display_list = glGenLists(1)
            glNewList(self.display_list, GL_COMPILE)
            glBegin(GL_QUADS)

            glVertex3d(l, b, z)
            glVertex3d(r, b, z)
            glVertex3d(r, t, z)
            glVertex3d(l, t, z)
            glEnd()

            glEndList()
        else:
            self.display_list = glGenLists(1)
            glNewList(self.display_list, GL_COMPILE)
            glBegin(GL_QUADS)

            glTexCoord2d(0.0,1.0)
            glVertex3d(l, b, z)
            glTexCoord2d(1.0,1.0)
            glVertex3d(r, b, z)
            glTexCoord2d(1.0,0.0)
            glVertex3d(r, t, z)
            glTexCoord2d(0.0,0.0)
            glVertex3d(l, t, z)
            glEnd()

            glEndList()

#A multi label is a label that can span multiple lines, constrained by a max_width
class MultiLabel(Widget):
    def __init__(self, **args):
        Widget.__init__(self, **args)
        self.text_lines = []

    #text is sent to this with line breaks specified as a '<br>'.
    #This acts as an explicit line break, while the widget itself will handle implicit
    #line breaks (single lines too long for the max_width)
    def set_text(self, text):
        ex_lines = text.split('<br>')

        fin_lines = []
        mw = self.rect.width

        for im_line in ex_lines:
            s = self.font.size(im_line)
            if s[0] < mw:
                fin_lines.append(im_line)
            else:
                words = im_line.split(' ')
                c_line = []
                p_len = 0
                for word in words:
                    p_len = p_len + self.font.size(word)[0]
                    if p_len > mw:
                        fin_lines.append(' '.join(c_line))
                        c_line = [word]
                        p_len = self.font.size(word)[0]
                    else:
                        c_line.append(word)
                if len(c_line) > 0:
                    fin_lines.append(' '.join(c_line))

        self.text_lines = fin_lines
        self.redraw()

    def draw_img(self):
        offset = [0, 0]
        h = self.font.get_linesize() * len(self.text_lines)
        if self.valign == 0:
            offset[1] = (self.rect.height - h) // 2
        elif self.valign == 1:
            offset[1] = self.rect.height - h

        self.image = pygame.Surface((self.rect[2], self.rect[3])).convert()

        for line in self.text_lines:
            w, h = self.font.size(line)

            #take into account the aligns
            #center horizontal align
            if self.align == 0:
                offset[0] = (self.rect.width - w) // 2

            #right align
            elif self.align == 1:
                offset[0] = self.rect.width - w

            line_img = self.font.render(line, True, self.color)
            self.image.blit(line_img, (offset[0], offset[1]))
            offset[1] += self.font.get_linesize()